<template>
	<view>
		<canvas type="webgl" class="canvasBox" id="canvasBox"
			:style="{width: screenWidth+'px', height: screenWidth+'px',}" @touchstart="touchStart"
			@touchmove="touchMove" @touchend="touchEnd"></canvas>
	</view>
</template>

<script>
	import * as THREE from '../static/threejs/libs/three.weapp.js'
	// import TWEEN from '@tweenjs/tween.js';
	import {
		OrbitControls
	} from '../static/threejs/jsm/controls/OrbitControls'

	let scene = null
	let camera = null
	let AllMeshArr = [] //所有的字母
	let currentLine = null
	let chooseMesh = null
	let chooseMeshArr = [] //选中的物体
	let selectedPositionArr = [] //选中的字母
	let selectedLetterArr = [] //选中的位置
	let isGestureStarted = false

	// 爆炸背景开裂效果
	// 创建一个数组来存储每一帧的纹理
	let textures = [];
	let frameCount = 10; // 假设有10帧
	let currentFrame = 0;
	let frameDelay = 100; // Delay between frame changes in milliseconds
	let lastFrameChangeTime = 0;
	let explodeMeshArr = [];
	let planeMaterial = null;

	// 五角星
	let starGeometry = null;
	let starMaterial = null;
	export default {
		props: ['word'], // 声明接收来自父组件的prop
		data() {
			return {
				title: 'game_word_link',
				screenWidth: 0,
				selectedPositionStr: '',
				selectedLetterStr: '',
				round: 1,
			}
		},
		watch: {
			word(newVal, oldVal) {
				this.round++;
				this.init()
			}
		},
		mounted() {
			// this.init()

		},
		methods: {
			init() {
				// 数组中随机获取一个元素
				function getRandomLetter() {
					var letters_26 = [
						"a", "b", "c", "d", "e", "f", "g",
						"h", "i", "j", "k", "l", "m", "n",
						"o", "p", "q", "r", "s", "t", "u",
						"v", "w", "x", "y", "z"
					];
					var randomIndex = Math.floor(Math.random() * letters_26.length); // 生成一个随机索引值
					return letters_26[randomIndex]; // 根据随机索引值获取相应位置上的元素
				}
				const guiParams = {
					fontColor: '#ffffff', // 字体颜色
					backgroundColor: '#fff000', // 背景颜色
					selectedFontColor: '#0000ff', // 选中的字体颜色
					selectedBackgroundColor: '#00ffff', // 选中的背景颜色
					rows: 7, //宫格行数
					cols: 7, //宫格列数
					spacing: 10, // 精灵模型之间的间距
				};

				var lettersObj = {
					// "00": "a",
					// "01": "a",
				};
				var lettersObj = {};
				for (var i = 0; i < guiParams.rows; i++) {
					for (var j = 0; j < guiParams.cols; j++) {
						lettersObj[i.toString() + j.toString()] = getRandomLetter();
					}
				}

				// lettersObj["00"] = "A";
				// lettersObj["01"] = "B";
				// lettersObj["02"] = "C";

				if (true) {
					if ('单条：不包括斜线' && true) {
						function generatePaths(numPaths, pathLength) {
							var paths = [];

							for (var i = 0; i < numPaths; i++) {
								var path = generatePath(pathLength);
								paths.push(path);
							}

							return paths;
						}

						function generatePath(pathLength) {
							var path = [];
							var directions = [{
									x: 0,
									y: -1
								}, // 上
								{
									x: 1,
									y: 0
								}, // 右
								{
									x: 0,
									y: 1
								}, // 下
								{
									x: -1,
									y: 0
								} // 左
							];

							var startX = Math.floor(Math.random() * guiParams.rows);
							var startY = Math.floor(Math.random() * guiParams.rows);

							var currentX = startX;
							var currentY = startY;

							path.push({
								x: currentX,
								y: currentY
							});

							while (path.length < pathLength) {
								var availableDirections = [];

								for (var i = 0; i < directions.length; i++) {
									var nextX = currentX + directions[i].x;
									var nextY = currentY + directions[i].y;

									if (nextX >= 0 && nextX <= (guiParams.rows - 1) && nextY >= 0 && nextY <= (guiParams
											.rows - 1)) {
										if (!path.some(function(point) {
												return point.x === nextX && point.y === nextY;
											})) {
											availableDirections.push(directions[i]);
										}
									}
								}

								if (availableDirections.length === 0) {
									break;
								}

								var randomDirection = availableDirections[Math.floor(Math.random() * availableDirections
									.length)];
								currentX += randomDirection.x;
								currentY += randomDirection.y;

								path.push({
									x: currentX,
									y: currentY
								});
							}

							// 将位置信息数组转换为字符串数组
							var stringPath = path.map(function(point) {
								return point.x + "" + point.y;
							});

							return stringPath;
						}


						var zhangtrArr = generatePaths(1, this.word.length);
						console.log('单条：不包括斜线')
						console.log(zhangtrArr)
						console.log('单条：不包括斜线')
						zhangtrArr = Array.from(zhangtrArr[0]).concat([]);
					}

					var wordArr = this.word.split('');
					for (let i = 0; i < zhangtrArr.length; i++) {
						const element = zhangtrArr[i];
						lettersObj[element] = wordArr[i];
					}
				}

				// console.log('单条：不包括斜线')
				// console.log(lettersObj)
				// console.log('单条：不包括斜线')
				this.screenWidth = uni.getSystemInfoSync().windowWidth - 80;
				// console.log(this.screenWidth)
				uni.createSelectorQuery().in(this).select('#canvasBox').fields({
					node: true,
					size: true
				}).exec((res) => {
					// console.log(res)
					let canvas = res[0].node;
					let canvasId = res[0].node._canvasId
					canvas.width = this.screenWidth;
					canvas.height = this.screenWidth;

					// 模型大小
					var spriteWidth = (this.screenWidth) / guiParams.cols; // 模型的宽度  

					canvas = THREE.global.registerCanvas(canvasId, canvas)

					// 场景
					scene = new THREE.Scene();
					scene.background = new THREE.Color(0xFFFFFF);

					// 渲染器
					const renderer = new THREE.WebGLRenderer({
						antialias: true
					});

					// 获取设备像素比
					uni.getSystemInfo({
						success: function(res) {
							const pixelRatio = res.pixelRatio;
							renderer.setPixelRatio(pixelRatio);
						}
					});

					//相机
					camera = new THREE.OrthographicCamera(
						this.screenWidth / -2,
						this.screenWidth / 2,
						this.screenWidth / 2,
						this.screenWidth / -2, 1, 1000
					);
					camera.position.set(0, 0, 700);
					camera.lookAt(0, 0, 700);

					//辅助观察的坐标系
					// const axesHelper = new THREE.AxesHelper(100);
					// scene.add(axesHelper);

					//光源设置
					const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
					directionalLight.position.set(100, 60, 50);
					scene.add(directionalLight);
					const ambient = new THREE.AmbientLight(0xffffff, 0.4);
					scene.add(ambient);

					if ('创建五角星') {
						// 创建五角星
						starGeometry = new THREE.PlaneGeometry(10, 10);
						// 创建一个纹理加载器
						var textureLoader1 = new THREE.TextureLoader();
						// 加载图片贴图
						var texture = textureLoader1.load("https://cdn.spbcn.org/miniprogram/image/star64.png");
						starMaterial = new THREE.MeshBasicMaterial({
							// map: texture,
							// transparent: true,
							color: 0xfbaa02
						});
					}

					if ('爆炸背景裂图') {
						const textureLoader2 = new THREE.TextureLoader();
						for (let i = 0; i < frameCount; i++) {
							let texture = textureLoader2.load(
								`https://cdn.spbcn.org/miniprogram/image/num/${i}.png`); // Load each frame
							textures.push(texture);
						}
						var frameIndex = 0;
						planeMaterial = new THREE.MeshBasicMaterial({
							// map: textures[frameIndex]
							color: 0xfbaa02
						});
					}

					// 创建宫格
					for (let i = 0; i < guiParams.cols; i++) {
						for (let j = 0; j < guiParams.cols; j++) {
							let currentLetter = lettersObj[i.toString() + j.toString()];

							let geometry = new THREE.CircleGeometry(spriteWidth / 2 - guiParams.spacing /
								2, 32);
							let texture = new THREE.TextureLoader().load('./pikachu.png');
							let material = new THREE.MeshBasicMaterial({
								// map: texture,
								// 未选中背景颜色
								color: 0xfbaa02
							});
							let mesh = new THREE.Mesh(geometry, material);
							mesh.position.set((j - Math.floor(guiParams.rows / 2)) * (spriteWidth),
								(i - Math.floor(guiParams.rows / 2)) * (spriteWidth),
								10); // 将平面放置在 x=1, y=2, z=3 的位置


							// 创建字体加载器
							let fontLoader = new THREE.FontLoader();
							// 加载字体文件
							fontLoader.load(
								'https://ftalk.soullions.com/threejs/fonts/helvetiker_bold.typeface.json',
								function(res) {
									// 在这里可以访问加载的字体数据
									let font = new THREE.TextBufferGeometry(currentLetter, {
										font: res,
										size: 18,
										height: 1
									});

									font.computeBoundingBox();

									// 创建字母的材质 - 未选中文字颜色
									let textMaterial = new THREE.MeshBasicMaterial({
										color: 0xffffff
									});

									// 创建字母的网格对象
									let textMesh = new THREE.Mesh(font, textMaterial);
									textMesh.userData.type = '字母'; //设置类型

									// 将字体模型的位置调整为居中
									let textBoundingBox = new THREE.Box3().setFromObject(textMesh);
									let textWidth = textBoundingBox.max.x - textBoundingBox.min.x;
									let textHeight = textBoundingBox.max.y - textBoundingBox.min.y;
									textMesh.position.x = -textWidth / 2;
									textMesh.position.y = -textHeight / 2;

									// 将字母添加到平面上
									mesh.add(textMesh);
								})

							// 设置自定义属性
							mesh.userData.letter = currentLetter; //设置字母
							mesh.userData.position = i.toString() + j.toString(); //设置位置
							mesh.userData.type = '平面'; //设置类型
							mesh.position.z += this.round;

							AllMeshArr.push(mesh);
							scene.add(mesh);
						}
					}

					// const controls = new OrbitControls(camera, renderer.domElement);
					// controls.enableDamping = true;
					// controls.update();
					console.log('scene:包括', scene)

					// const controls = new OrbitControls(camera, renderer.domElement);

					function updateGifTexture() {
						currentFrame = (currentFrame + 1) % frameCount;
						var offsetX = 1 / frameCount * currentFrame;
						texture.offset.set(offsetX, 0);
					}

					function render() {
						// scene.position.z += 0.01;
						canvas.requestAnimationFrame(render);
						// 更新控制器
						// controls.update();
						renderer.render(scene, camera);
						if (Date.now() - lastFrameChangeTime > frameDelay) {
							planeMaterial.map = textures[frameIndex];
							frameIndex = (frameIndex + 1) % frameCount;
							lastFrameChangeTime = Date.now();
						}
						try {
							TWEEN.update();
						} catch (e) {
							//TODO handle the exception
						}
					}

					render()
				});
			},

			touchStart(e) {
				// THREE.global.touchEventHandlerFactory('canvas', 'touchstart')(e)
				isGestureStarted = true
			},

			touchMove(e) {
				e.preventDefault(); // 阻止默认事件

				if (currentLine) {
					scene.remove(currentLine);
				}
				// THREE.global.touchEventHandlerFactory('canvas', 'touchmove')(e)
				if (isGestureStarted) {
					// 处理触摸移动事件
					var touch = e.touches[0];
					var Sx = touch.x; //鼠标单击位置横坐标
					// var Sy = touch.y - 50; //鼠标单击位置纵坐标【手机端需要减去margin-top的值】
					var Sy = touch.y; //鼠标单击位置纵坐标【手机端需要减去margin-top的值】
					// console.log('Sx:', Sx)
					// console.log('Sy:', Sy)
					//屏幕坐标转WebGL标准设备坐标
					var x = (Sx / this.screenWidth) * 2 - 1; //WebGL标准设备横坐标
					var y = -((Sy) / this.screenWidth) * 2 + 1; //WebGL标准设备纵坐标

					if ('画线') {
						const vector = new THREE.Vector3(x, y, 0.5);
						vector.unproject(camera);

						const dir = vector.sub(camera.position).normalize();
						const distance = -camera.position.z / dir.z;
						const pos = camera.position.clone().add(dir.multiplyScalar(distance));

						// 画球和鼠标之间的连线
						if (chooseMeshArr.length >= 1) {
							this.drawLineV2(chooseMeshArr[chooseMeshArr.length - 1].position.clone(), pos);
						}
					}

					if ('射线拾取') {
						//创建一个射线投射器`Raycaster`
						var raycaster = new THREE.Raycaster();
						//通过鼠标单击位置标准设备坐标和相机参数计算射线投射器`Raycaster`的射线属性.ray
						raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
						//返回.intersectObjects()参数中射线选中的网格模型对象
						// 未选中对象返回空数组[],选中一个数组1个元素，选中两个数组两个元素
						var intersects = raycaster.intersectObjects(AllMeshArr);
						if (intersects.length > 0) {
							chooseMesh = intersects[0].object;
							var result = selectedPositionArr.includes(chooseMesh.userData.position);
							if (!result) {
								chooseMeshArr.push(chooseMesh)
								selectedPositionArr.push(chooseMesh.userData.position);
								selectedLetterArr.push(chooseMesh.userData.letter);

								this.onSpriteSelected(chooseMesh);
							}
						}
					}


				}
			},

			touchEnd(e) {
				// THREE.global.touchEventHandlerFactory('canvas', 'touchend')(e)
				this.selectedPositionStr = selectedPositionArr.join(',');
				this.selectedLetterStr = selectedLetterArr.join(',');

				//触发父组件方法
				this.$emit("pThumbsUp", {
					selectedPositionStr: selectedPositionArr.join(','),
					selectedLetterStr: selectedLetterArr.join(','),
				})

				for (let i = 0; i < chooseMeshArr.length; i++) {
					let item = chooseMeshArr[i];
					item.material.color.set(0xfbaa02); // 选中背景颜色

					// 遍历PlaneGeometry的子对象
					item.children.forEach(child => {
						// 判断子对象是否是字体模块
						if (child.userData.type === '字母') {
							// 恢复字体模块的颜色
							child.material.color.set(0xffffff); // 选中文字颜色
						}
					});
				}

				if (isGestureStarted) {
					isGestureStarted = false

					console.log('chooseMeshArr.length', chooseMeshArr.length)

					// 在这里可以执行手势结束时的操作
					// 可以使用 gesturePath 数组来判断手势是否符合您的要求
					for (let index = 0; index < chooseMeshArr.length; index++) {
						const element = chooseMeshArr[index];
						console.log('xxxxxxxxxxxxxxxxxxxxxxx')
						this.aaa(element); //爆炸星星特效
						// this.bbb(element); //背景特效
					}

					if (currentLine) {
						scene.remove(currentLine);
					}

					chooseMeshArr = [];
					selectedPositionArr = [];
					selectedLetterArr = [];
				}

				console.log('结束啦！！！')
			},

			// 选中精灵模型的事件处理函数
			onSpriteSelected(chooseMesh) {
				if (chooseMeshArr.length >= 2) {
					this.drawLine(chooseMeshArr[chooseMeshArr.length - 1].position.clone(), chooseMeshArr[chooseMeshArr
						.length - 2].position.clone());
				}
				// 震动
				// uni.vibrateShort({
				// 	success: function() {
				// 		console.log('短暂震动');
				// 	},
				// 	fail: function(err) {
				// 		console.error('震动失败', err);
				// 	}
				// });

				chooseMesh.material.color.set(0xf96800); // 选中背景颜色
				// console.log('chooseMesh=', chooseMesh)

				// 遍历PlaneGeometry的子对象
				chooseMesh.children.forEach(child => {
					// 判断子对象是否是字体模块
					if (child.userData.type === '字母') {
						// 恢复字体模块的颜色
						child.material.color.set(0x000000); // 选中文字颜色
					}
				});
			},

			// 五角星散开特效
			aaa(circle) {
				let currentCircle = circle;
				let starCount = 3;
				let stars = [];

				console.log('五角星散开特效')
				for (let i = 0; i < starCount; i++) {
					let star = new THREE.Mesh(starGeometry, starMaterial);
					star.position.set(circle.position.x, circle.position.y, 110);
					stars.push(star);
					scene.add(star);
				}

				// 创建动画效果
				let duration1 = 0.5; // 第一段动画持续时间
				let duration2 = 0.1; // 第二段动画持续时间
				let delay = 0.001; // 延迟时间
				let targetDistance = 10; // 目标距离
				let distance = 0;
				let tween1 = new TWEEN.Tween({
						distance: 0
					})
					.to({
						distance: targetDistance
					}, duration1 * 1000)
					.delay(delay * 1000)
					.easing(TWEEN.Easing.Quadratic.Out)
					.onUpdate(() => {
						distance += 1;
						stars.forEach(function(star, index) {
							let angle = ((Math.PI * 2) / starCount) * index;
							let newX = circle.position.x + distance * Math.cos(angle);
							let newY = circle.position.y + distance * Math.sin(angle);
							star.position.set(newX, newY, 110);

							// 根据距离调整星星的大小
							let distanceToCenter = Math.sqrt(
								Math.pow(newX - circle.position.x, 2) +
								Math.pow(newY - circle.position.y, 2)
							);
							let scaleFactor = distanceToCenter / targetDistance; // 根据距离计算缩放比例
							if (index % 2 == 1) {
								star.scale.set(scaleFactor, scaleFactor, 1); // 设置星星的缩放
							} else {
								star.scale.set(
									(scaleFactor - (targetDistance - distance)) / targetDistance,
									(scaleFactor - (targetDistance - distance)) / targetDistance,
									1
								);
							}
						});
					});
				let opacity = 1;
				let tween2 = new TWEEN.Tween({
						opacity: 1
					})
					.to({
						opacity: 0
					}, duration2 * 1000)
					.easing(TWEEN.Easing.Quadratic.In)
					.onUpdate(function() {
						opacity -= 0.1;
						stars.forEach(function(star) {
							star.material.opacity = opacity;
						});
					})
					.onComplete(function() {
						// 在动画结束时执行一些操作，比如移除五角星
						stars.forEach(function(item) {
							scene.remove(item);
						});
						console.log('添加字母---1》')
						scene.add(currentCircle);
						if (explodeMeshArr.length) {
							explodeMeshArr.forEach(function(item) {
								scene.remove(item);
							});
						}
					});

				// 串联两段动画
				tween1.chain(tween2);

				// 在第一段动画结束后，开始第二段动画
				tween1.onComplete(function() {
					tween2.start();
				});

				// 开始第一段动画
				tween1.start();
				scene.remove(circle);
			},

			// 爆炸背景特效
			/**
			 * 函数bbb
			 * @param {THREE.Object3D} circle - 圆形对象
			 */
			bbb(circle) {
				return false;
				console.log('爆炸背景特效--->')
				// 创建平面几何体
				const planeGeometry = new THREE.PlaneGeometry(50, 50);
				// 创建平面网格
				const plane = new THREE.Mesh(planeGeometry, planeMaterial);
				// 设置平面位置
				plane.position.set(circle.position.x, circle.position.y, 110);
				// 将平面添加到爆炸网格数组中
				explodeMeshArr.push(plane);
				// 将平面添加到场景中
				scene.add(plane);
			},

			// 画线：两球之间的连线
			drawLine(center1, center2) {
				if (currentLine) {
					scene.remove(currentLine);
				}

				// 计算连接两个球体的连线向量
				const lineDirection = new THREE.Vector3().subVectors(center2, center1).normalize();

				// 计算线条的中心位置
				const lineCenter = new THREE.Vector3()
					.addVectors(center1, center2)
					.multiplyScalar(0.5);

				// 创建圆柱体几何体
				const cylinderGeometry = new THREE.CylinderGeometry(
					6,
					6,
					center1.distanceTo(center2),
					32
				);

				// 创建线条材质
				const cylinderMaterial = new THREE.MeshBasicMaterial({
					color: 0x00ff00,
				});

				// 创建圆柱体网格对象
				const line = new THREE.Mesh(cylinderGeometry, cylinderMaterial);

				// 设置线条位置和旋转
				line.position.copy(lineCenter);
				line.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), lineDirection);
				line.position.z = -10;

				// 将线条添加到场景中
				scene.add(line);
			},

			// 画线：鼠标跟球之间的连线
			drawLineV2(center1, center2) {
				// 计算连接两个球体的连线向量
				const lineDirection = new THREE.Vector3().subVectors(center2, center1).normalize();

				// 计算线条的中心位置
				const lineCenter = new THREE.Vector3()
					.addVectors(center1, center2)
					.multiplyScalar(0.5);

				// 创建圆柱体几何体
				const cylinderGeometry = new THREE.CylinderGeometry(
					6,
					6,
					center1.distanceTo(center2),
					32
				);

				// 创建线条材质
				const cylinderMaterial = new THREE.MeshBasicMaterial({
					color: 0x00ff00,
				});

				// 创建圆柱体网格对象
				const line = new THREE.Mesh(cylinderGeometry, cylinderMaterial);

				// 设置线条位置和旋转
				line.position.copy(lineCenter);
				line.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), lineDirection);
				// 将线条添加到场景中
				line.position.z = -10;
				currentLine = line;
				scene.add(line);
			},

		}
	}
</script>

<style>
	page {
		overflow: hidden;
	}

	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.canvasBox {
		background-color: #fff;
		border-radius: 40rpx;
		margin: 0 auto;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>